#include "dccapture.h"
#include <QGuiApplication>
#include <QDebug>
#include <QWindow>
#include <QMouseEvent>
#include <QCursor>
#include <QScreen>

DcCapture::DcCapture(int /*widId*/, QObject *parent)
    : ScreenCapture(parent), m_deskBM(nullptr), m_winId(0)
{
    m_deskDC = GetDC(reinterpret_cast<HWND>(m_winId));
    m_memDC = ::CreateCompatibleDC(m_deskDC);
    m_winId = reinterpret_cast<intptr_t>(WindowFromDC(m_deskDC));
//    m_deskBM = ::CreateCompatibleBitmap(m_deskDC, this->width(), this->height());
//    SelectObject(m_memDC, m_deskBM);
}

DcCapture::~DcCapture()
{
    DeleteObject(m_deskBM);
    DeleteDC(m_memDC);
    ReleaseDC(nullptr, m_deskDC);
}

// 暂时写这里，以后要区分系统或者查询
AVPixelFormat DcCapture::pixelFormat()
{
    return AV_PIX_FMT_BGRA;
}

int DcCapture::x()
{
    RECT rect;
    ::GetWindowRect(reinterpret_cast<HWND>(m_winId), &rect);
    return rect.left;
}

int DcCapture::y()
{
    RECT rect;
    ::GetWindowRect(reinterpret_cast<HWND>(m_winId), &rect);
    return rect.top;
}

int DcCapture::width()
{
    RECT rect;
    ::GetWindowRect(reinterpret_cast<HWND>(m_winId), &rect);
    return rect.right - rect.left;
}

int DcCapture::height()
{
    RECT rect;
    ::GetWindowRect(reinterpret_cast<HWND>(m_winId), &rect);
    return rect.bottom - rect.top;
}

int DcCapture::winId()
{
    return 0;
}

QByteArray DcCapture::getFramebuffer()
{
    QByteArray data;
    getFramebuffer(data);
    return data;
}

void DcCapture::getFramebuffer(QByteArray &data)
{
    int width = this->width();
    int height = this->height();
    int size = width*height*4;
    if(data.size()<size)
    {
        data.resize(size);
    }
    getFramebuffer(data.data());
}

void DcCapture::getFramebuffer(char *data)
{
    int width = this->width();
    int height = this->height();
    m_deskBM = ::CreateCompatibleBitmap(m_deskDC, width, height);
    SelectObject(m_memDC, m_deskBM);

    BITMAP bitmap;
    // 获取屏幕图像数据
    BitBlt(m_memDC, 0, 0, width, height, m_deskDC, 0, 0, SRCCOPY);//拷贝DC
    GetObject(m_deskBM, sizeof(BITMAP), &bitmap);
    int size = (bitmap.bmHeight * bitmap.bmWidth * bitmap.bmBitsPixel) / 8;

    // BGRA
    int ret = GetBitmapBits(m_deskBM, size, data);
    if(ret != size)
    {
        qWarning()<<"获取数据大小与预期不同";
    }

    DeleteObject(m_deskBM);
}

void DcCapture::postMouseEvent(int button, bool isPress, int x, int y)
{
    INPUT ip;
    ip.type = INPUT_MOUSE;
    ip.mi.dx = 0;
    ip.mi.dy = 0;

    Qt::MouseButtons btn = Qt::MouseButtons(button);
    if(btn.testFlag(Qt::MouseButton::LeftButton))
    {
        ip.mi.mouseData = 0;
        if(isPress)
        {
            ip.mi.dwFlags |= MOUSEEVENTF_LEFTDOWN;
        }
        else
        {
            ip.mi.dwFlags |= MOUSEEVENTF_LEFTUP;
        }
    }
    if(btn.testFlag(Qt::MouseButton::RightButton))
    {
        ip.mi.mouseData = 0;
        if(isPress)
        {
            ip.mi.dwFlags |= MOUSEEVENTF_RIGHTDOWN;
        }
        else
        {
            ip.mi.dwFlags |= MOUSEEVENTF_RIGHTUP;
        }
    }
    if(btn.testFlag(Qt::MouseButton::MidButton))
    {
        ip.mi.mouseData = 0;
        if(isPress)
        {
            ip.mi.dwFlags |= MOUSEEVENTF_MIDDLEDOWN;
        }
        else
        {
            ip.mi.dwFlags |= MOUSEEVENTF_MIDDLEUP;
        }
    }
    if(button == Qt::MouseButton::NoButton)
    {
        ip.mi.mouseData = 0;
        ip.mi.dwFlags |= MOUSEEVENTF_MOVE;
    }

    ip.mi.time = 0;
    ip.mi.dwExtraInfo = 0;
    QCursor::setPos(x+this->x(), y+this->y());

    SendInput(1, &ip, sizeof(INPUT));
}

void DcCapture::postKeyEvent(int key, bool isPress)
{
    INPUT ip;
    ip.type = INPUT_KEYBOARD;
    ip.ki.wVk = translateKeyCode(key);
    ip.ki.time = 0;
    ip.ki.wScan = 0;
    ip.ki.dwFlags = isPress?0:KEYEVENTF_KEYUP;
    ip.ki.dwExtraInfo = 0;
    SendInput(1, &ip, sizeof(INPUT));
}

void DcCapture::postWheelEvent(int delta)
{
    qDebug()<<"delta:"<<delta;
    INPUT ip;
    ip.type = INPUT_MOUSE;
    ip.mi.dwFlags |= MOUSEEVENTF_WHEEL;
    ip.mi.dx = 0;
    ip.mi.dy = 0;
    ip.mi.mouseData = static_cast<unsigned long>(delta);
    ip.mi.time = 0;
    ip.mi.dwExtraInfo = 0;
    SendInput(1, &ip, sizeof(INPUT));
}

int DcCapture::translateKeyCode(int key)
{
    int k = key;
    bool legal = true;
    if(k >= Qt::Key_0 && k <= Qt::Key_9)
    {
    }
    else if(k >= Qt::Key_A && k <= Qt::Key_Z)
    {
    }
    else if(k >= Qt::Key_F1 && k <= Qt::Key_F24)
    {
        k &= 0x000000ff;
        k += 0x40;
    }
    else if(k == Qt::Key_Tab)
    {
        k = 0x09;
    }
    else if(k == Qt::Key_Backspace)
    {
        k = 0x08;
    }
    else if(k == Qt::Key_Return)
    {
        k = 0x0d;
    }
    else if(k <= Qt::Key_Down && k >= Qt::Key_Left)
    {
        int off = k - Qt::Key_Left;
        k = 0x25 + off;
    }
    else if(k == Qt::Key_Shift)
    {
        k = 0x10;
    }
    else if(k == Qt::Key_Control)
    {
        k = 0x11;
    }
    else if(k == Qt::Key_Alt)
    {
        k = 0x12;
    }
    else if(k == Qt::Key_Meta)
    {
        k = 0x5b;
    }
    else if(k == Qt::Key_Insert)
    {
        k = 0x2d;
    }
    else if(k == Qt::Key_Delete)
    {
        k = 0x2e;
    }
    else if(k == Qt::Key_Home)
    {
        k = 0x24;
    }
    else if(k == Qt::Key_End)
    {
        k = 0x23;
    }
    else if(k == Qt::Key_PageUp)
    {
        k = 0x21;
    }
    else if(k == Qt::Key_Down)
    {
        k = 0x22;
    }
    else if(k == Qt::Key_CapsLock)
    {
        k = 0x14;
    }
    else if(k == Qt::Key_NumLock)
    {
        k = 0x90;
    }
    else if(k == Qt::Key_Space)
    {
        k = 0x20;
    }
    else
        legal = false;

    if(!legal)
        return 0;
    return k;
}
